package org.example.project.common.error.handle.third;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.example.project.common.util.AspectLogUtils;
import org.example.project.common.error.util.ErrorHandleUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestOperations;

/**
 * 第三方调用日志处理切面
 * <p>
 * 1. 拦截数据存储访问异常
 * 2. 拦截中间件访问异常
 * 3. 拦截第三方系统访问异常
 * 4. 返回C类错误码
 * ×    记录日志，封装C类错误码返回
 *
 * @author wenxy
 * @date 2020/11/6
 */
@Component
@Aspect
@Slf4j
@ConditionalOnClass(RestOperations.class)
public class RestLogAspect {

    /**
     * 启停切面
     * 通过属性有2种方式，
     * 1. 是通过属性@ConditionalOnProperty，控制切面bean
     * 2. 增加变量
     */
    @Value("${yundasys.vienna.common.dao-log.enable:true}")
    boolean enable;

    @Pointcut("this(org.springframework.web.client.RestOperations)")
    public void pointCut() {
    }

    /**
     * 第三方调用记录正常方法出入口信息仅debug级别（开发测试开启）
     *
     * @param joinPoint 切点
     * @param result    响应结果
     */
    @AfterReturning(pointcut = "pointCut()", returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {
        if (isEnable() && log.isDebugEnabled()) {
            log.debug(AspectLogUtils.buildLog(joinPoint, result).toString());
        }
    }

    /**
     * 第三方调用异常记录，
     * 附加异常方法出入口信息，重新抛出
     *
     * @param joinPoint 切点
     * @param e         异常
     */
    @AfterThrowing(pointcut = "pointCut()", throwing = "e")
    public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
        if (isEnable()) {
            ErrorHandleUtils.handleThirdException(joinPoint, e, log);
        }
    }

    boolean isEnable() {
        return enable;
    }

}
